#define _J_SPREMNIK_C_
#include "spremnik.h"

#include "postavke.h"
#include "razno.h"
#include "ispis.h"
#include "liste.h"
#include "procesi.h"
#include "prekidi.h"
#include "stranicenje.h"
#include <arh/kontekst.h>

void j_inicijaliziraj_spremnik()
{
	//+++ upravljanje spremnikom segmentima (uglavnom) +++
	arh_inicijalizacija_spremnika();

	//opisnici procesa i dretvi nalaziti ce se na pocetku spremnika, iza
	//prve stranice (koja sadrzi globalne podatke i kod za prihvat prekida)
	//->nedostupno za korisnicke dretve!

	extern char kraj_prve_stranice;
	void *opisnici_za_procese;
	void *opisnici_za_dretve;

	opisnici_za_procese = (void *) &kraj_prve_stranice;

	opisnici_za_dretve = opisnici_za_procese +
				j_velicina_opisnika_procesa() * NAJ_PROCESA;

	j_postavi_opisnike_procesa ( opisnici_za_procese );
	j_postavi_opisnike_dretvi ( opisnici_za_dretve );

	//+++ upravljanje spremnikom stranicenjem +++
	j_inicijaliziraj_stranicenje ();
}

//Ako se stranicenje ne koristi, mjesto za kontekst dretvi je iza opisnika
//dretvi (na pocetku, iza IDT, GDT, TSS, koda za prihvat prekida i opisnika)
//Pri stvaranju dretve njen se opisnik povezuje s mjestom za kontekst
inline void *j_spremnik_za_kontekst ( int id_dretve )
{
	extern char kraj_prve_stranice;

	return ( (void *) &kraj_prve_stranice ) +
		j_velicina_opisnika_procesa() * NAJ_PROCESA +
		j_velicina_opisnika_dretvi() * NAJ_DRETVI * NAJ_PROCESA +
		sizeof(arh_kontekst_t) * id_dretve;
}

//pri stvaranju novog procesa => "priprema" se spremnicki prostor za novi proces
void j_inicijaliziraj_spremnik_za_proces ( int proces_id,
					   void *pocetna_adresa,
					   uint velicina,
					   bool u_jezgri, bool stranicenje )
{
	j_spremnik_t *spremnik = j_oppr_spremnik ( proces_id );

	//postavi segmentne registre i zauzmi spremnik (ako se koristi
	//upravljanje spremnikom segmentacijom)
	arh_zauzmi_spremnik ( &spremnik->segmentacija, pocetna_adresa,
				velicina, u_jezgri, stranicenje );

	int i;

	if ( !stranicenje )
	{
		//mjesto za stogove dretvi (logicka adresa!)
		extern char pocetak_mjesta_za_stog;
		spremnik->stogovi = (void *) &pocetak_mjesta_za_stog +
					NAJ_DRETVI * VEL_STRANICE;
	}
	else {
		j_inicijaliziraj_stranice_za_proces (	proces_id,
							pocetna_adresa,
							velicina,
							u_jezgri,
							stranicenje );
	}

	//inicijaliziraj maske za stogove
	memset ( spremnik->mstogovi, 0, velicina_maske ( NAJ_DRETVI ) );

	for ( i = 0; i < NAJ_DRETVI; i++ )
		POSTAVI_SLOBODNO ( spremnik->mstogovi, NAJ_DRETVI, i );
}

void j_oslobodi_spremnicki_prostor_procesa ( void *_spremnik )
{
	j_spremnik_t *spremnik = _spremnik;

	if ( spremnik->stranicenje )
		j_oslobodi_spremnicki_prostor ( spremnik );
}

//prije povratka u dretvu treba pripremiti opisnike segmenata i stranicenja
void j_pripravi_okolinu_dretvi ()
{
	arh_pripravi_okolinu_dretvi ( j_dohvati_kontekst_aktivne() );
}
